<!--编辑表格会高亮显示上一次编辑的列-->
<!--因为要遍历转成input编辑表格，所以全部采用字符串类型，比如学号-->
<!--使用正则表达式进行搜索-->
<!--使用v-blind动态设置编辑按钮样式-->
<!--使用v-for生成表格-->
<!--使用watch监听修改内容-->
<!--使用v-if切换编辑模式和浏览模式-->
<!--使用computed统计性别比例之类-->
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>学生管理系统</title>
	<script src="js/vue.js"></script>
	<style>
		*{margin: 0;padding: 0}/*这是一个习惯*/
		#app table{
			border: #484848 solid 2px;
			width: 100vw;
			background: #298cdc;
		}
		#app table *{
			table-layout: revert;
		}
		#app tr:nth-child(even),.th1{
			background: #74a6ff;
			height: 30px;
		}
		#app tr:nth-child(odd){
			background: #bbb;
			height: 30px;
		}
		#app tr:nth-child(even) input{
			background: #d7e7ff;
			border: 0;
		}
		#app tr:nth-child(odd) input{
			border: 0;
		}
		.operation{
			text-align: center;
			user-select: none;
			width: 50px;
		}
		.operation:hover,.addButton:hover,.submitButton:hover{
			background: #cbcbcb;
		}
		.edit{
			background: #dad052;
		}
		.save,.addButton{
			background: #9f9;
		}
		.del,.submitButton{
			background: #da7756;
		}
		.lastSave{
			color: blueviolet;
		}
	</style>
</head>
<body>
<div id="app">
	<form action="" @submit.prevent="submitF()">
		<div class="control" style="user-select: none;">
			<div class="sorts">
				排序方式：
				<label v-for="(i,index) in sortTypes">
					<input type="radio" name="sort" v-model="sort" :value="index">
					{{i}}&nbsp;&nbsp;
				</label>
				<label>
					<input type="checkbox" v-model="order" value="1">
					逆序
				</label>
			</div>
			<hr>
			<div class="search">
				<label>查找表中内容：
					<input v-model="search" placeholder="/\d/   正则，\d是默认值">
				</label>
			</div>
			<hr>
			<div class="tableEdit">
				<input type="button" class="addButton" @click="addF" value="添加新的数据"></input>
				<button class="submitButton">提交当前的更改</button>
			</div>
			<hr>
		</div>
		<table>
			<thead>
			<tr>
				<th class="th1" v-for="i in thead_th">{{i}}</th>
				<th class="th1" colspan="2" width="10%" style="user-select: none">操作</th>
			</tr>
			</thead>
			<tbody>
			<tr v-for="(i,index) in tbody_tr" :class="index === lastSave?'lastSave':''" v-if="searchRegex.test(index + 1 + JSON.stringify(i))">
				<th width="5%">{{index+1}}</th>
				<td v-for="(j,key,indexTd) in i" v-if="key!=='inEdit'" :id="'td['+indexTd+','+index+']'">
					<div v-show="!i.inEdit">{{j}}</div>
					<div v-show="i.inEdit" style="text-align: center;display: flex"><label>
						<input @focusin="getIndexF(index)" v-model="i[key]" :name="i[key]" style="height: 39px;font-weight: bolder;width: 100%;">
					</label></div>
				</td>
				<td @click="editF(index)" v-show="!i.inEdit" class="edit operation">编辑</td>
				<td @click="saveF(index)" v-show="i.inEdit" class="save operation">保存</td>
				<td @click="delF(index)" class="del operation">删除</td>
				<!--			<td @click="cancelF(index)" v-show="i.inEdit" class="del operation">取消</td>-->
			</tr>
			</tbody>
		</table>
	</form>
	<footer>
		<div>
			<h4>全局统计</h4>
			平均年龄：{{avgAge}}<br>
			男女比例：{{maleNum}}/{{tbody_tr.length-maleNum}}
		</div>
	</footer>
	<hr>Debug:<br>{{debugD}}<br>
</div>
<script>
	const tbody_tr=[
		{name:"小明",sex:"男",age:"20",sno:"1000",classes:"软件工程",department:"软件与通信学院",inEdit: false},
		{name:"阿瞒",sex:"男",age:"20",sno:"1001",classes:"通信工程",department:"软件与通信学院",inEdit: false},
		{name:"你好",sex:"男",age:"22",sno:"1002",classes:"通信工程",department:"软件与通信学院",inEdit: false},
		{name:"花园",sex:"女",age:"21",sno:"1003",classes:"软件工程",department:"软件与通信学院",inEdit: false},
		{name:"北国",sex:"男",age:"19",sno:"1004",classes:"通信工程",department:"软件与通信学院",inEdit: false},
		{name:"Steve",sex:"男",age:"23",sno:"1005",classes:"软件工程",department:"软件与通信学院",inEdit: false},
		{name:"艾利克斯",sex:"女",age:"23",sno:"1006",classes:"软件工程",department:"软件与通信学院",inEdit: false},
		{name:"张三",sex:"男",age:"20",sno:"1007",classes:"软件工程",department:"软件与通信学院",inEdit: false},
	]
	new Vue({
		el:"#app",
		data:{
			debugD:'',
			sort:0,
			order:0,
			search:"",
			searchRegex:/\d/,
			editId:-1,
			lastSave:-1,
			indexOfTd:[-1,-1],
			sortTypes:["按学号","按年龄","按姓名"],
			thead_th:["","姓名","性别","年龄","学号","班级","院系"],
			tbody_tr:'',
			originalData: [],
			sno:[],
		},
		methods:{
			submitF(){
				this.sno=[]
				for (var i in this.tbody_tr){
					this.sno+=(this.tbody_tr[i].sno)+","
				}
				let set = this.sno.split(',')
				for (let i = 0;i<set.length;i++){
					for (let j = i+1;j<set.length;j++){
						if (set[i]===set[j]){
							alert("存在学号相同的学生!学号:"+set[i])
							return false
						}
					}
				}
				// alert(this.tbody_tr)
				return set[0]
			},
			addF(){
				this.$set(this.tbody_tr,this.tbody_tr.length,
					{name:"Steve",sex:"男",age:"23",sno:"1005",classes:"软件工程",department:"软件与通信学院",inEdit: false},
				)
			},
			getIndexF(index){
				this.editId = index
			},
			editF(index){
				this.originalData[index] = { ...this.tbody_tr[index] };
				this.tbody_tr[index].inEdit = true
			},
			saveF(index){
				this.tbody_tr[index].inEdit = false
			},
			delF(index){
				this.lastSave = index
				this.tbody_tr.splice(index,1)
			},
			// cancelF(index){//暂时无法完成取消模式
			// 	this.tbody_tr[index] = { ...this.originalData[index] };
			// 	this.tbody_tr[index].inEdit = false
			// },
			sortF(){
				if (!this.order)
					switch (this.sort){
						case 0:this.tbody_tr.sort((a,b)=>a.sno-b.sno);break
						case 1:this.tbody_tr.sort((a,b)=>a.age-b.age);break
						case 2:this.tbody_tr.sort((a,b)=>a.name.localeCompare(b.name));break
						default:break
					}
				else
					switch (this.sort){
						case 0:this.tbody_tr.sort((b,a)=>a.sno-b.sno);break
						case 1:this.tbody_tr.sort((b,a)=>a.age-b.age);break
						case 2:this.tbody_tr.sort((b,a)=>a.name.localeCompare(b.name));break
						default:break
					}
			},
			lastEditTbF(x,y){
				document.getElementById("td["+x+","+y+"]")
			}
		},
		created(){
			this.tbody_tr = tbody_tr
		},
		watch:{
			search(){
				var searchV = this.search === ""?"\\d":this.search
				this.searchRegex = eval("/"+searchV+"/")
			},
			sort(){
				this.sortF()
			},
			order(){
				this.sortF()
			},
			tbody_tr: {
				handler(newValue){
					if(newValue[this.editId].name) {
						if(newValue[this.editId].name.length>12){
							newValue[this.editId].name =
								newValue[this.editId].name.slice(0,-1)
						}
					}
					if(newValue[this.editId].sex) {
						if(!/^[男女]$/.test(newValue[this.editId].sex)){
							newValue[this.editId].sex = "男"
						}
					}
					if(newValue[this.editId].age) {
						newValue[this.editId].age =
							newValue[this.editId].age.replace(/\D/g,"")
					}
					if(newValue[this.editId].sno) {
						newValue[this.editId].sno =
							newValue[this.editId].sno.replace(/\D/g,"")
					}
					if(newValue[this.editId].classes) {
						if(newValue[this.editId].classes.length>12){
							newValue[this.editId].classes =
								newValue[this.editId].classes.slice(0,-1)
						}
					}
					if(newValue[this.editId].department) {
						if(newValue[this.editId].department.length>30){
							newValue[this.editId].department =
								newValue[this.editId].department.slice(0,-1)
						}
					}
					this.lastSave = this.editId
					this.lastEditTbF(this.lastSave,this)
				},
				deep:true
			}
		},
		computed:{
			avgAge(){
				var result = 0
				for (var i in this.tbody_tr){
					result += parseInt(this.tbody_tr[i].age)
				}
				return result / this.tbody_tr.length
			},
			maleNum(){
				var result = 0
				for (var i in this.tbody_tr){
					if (this.tbody_tr[i].sex === "男")
						result++
				}
				return result
			},
		}
	})
</script>
</body>
</html>